__author__ = 'Brandon Corfman'
from abc import ABCMeta, abstractmethod

class Agent(object):
    __metaclass__ = ABCMeta

    def __init__(self, hand, num_players):
        """
        states: BrokenTool cards that are active for the player.
        parent: reference to the parent class that holds the Agent.
        hand: list of cards that the player is holding at the beginning of the round.
        """
        self.states = []
        self.hand = hand
        self.parent = None
        self.num_players = num_players
        self.subscribers = set()

    def set_parent(self, parent):
        """ Sets a reference to the parent object that contains the Agent object. """
        self.parent = parent

    def add_state(self, state):
        """ Adds a state to the list of states. """
        self.states.append(state)

    def get_states(self):
        """ Returns the list of states. """
        return self.states

    def remove_state(self, state):
        """ Removes a state from the list of states. """
        if state in self.states:
            self.states.remove(state)

    def subscribe(self, subscriber):
        """ When an Action is completed by the Agent, each subscriber in this set
        will be notified. """
        self.subscribers.add(subscriber)

    def unsubscribe(self, subscriber):
        """ Removes an existing subscriber from the subscriber set, meaning they
        will no longer be notified when an Action is performed by the Agent. """
        if subscriber in self.subscribers:
            self.subscribers.remove(subscriber)

    def notify(self, msg):
        """ Sends all subscribers a message about an Action that has taken place by
        the Agent. The 'msg' parameter is just a string. """
        for subscriber in self.subscribers:
            subscriber.receive(msg)

    @abstractmethod
    def receive(self, msg):
        """ Receives a message string containing information about an Action that
        has taken place by another Agent. The 'msg' parameter is just a string. """
        pass

    @abstractmethod
    def decide_path_card(self, board, card):
        pass

    @abstractmethod
    def decide_broken_tool(self, board, state, others):
        pass

    @abstractmethod
    def decide_rockfall(self, board, card):
        pass

    @abstractmethod
    def decide_repair_one(self, board, card, others):
        pass

    @abstractmethod
    def decide_repair_any(self, board, card, others):
        pass

    @abstractmethod
    def decide_peek(self, board, card):
        pass

    @abstractmethod
    def decide_discard(self, board, card):
        pass